package com.bsj.travel.device.web.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.fastjson2.JSON;
import com.bsj.travel.config.rocketmq.producer.BaseMqPushUtil;
import com.bsj.travel.constant.BaseServerTopicConstants;
import com.bsj.travel.def.common.DTO.mqtt.MqttEvent;
import com.bsj.travel.def.common.DTO.mqtt.MqttEventPublish;
import com.bsj.travel.def.common.DTO.web.device.DeviceDTO;
import com.bsj.travel.def.common.DTO.web.device.DeviceParamDTO;
import com.bsj.travel.def.common.DTO.web.device.DeviceRemarkDTO;
import com.bsj.travel.def.common.DTO.web.device.DeviceSearchDTO;
import com.bsj.travel.def.common.VO.device.*;
import com.bsj.travel.def.global.JsonResult;
import com.bsj.travel.def.global.JsonResultEnum;
import com.bsj.travel.def.mqtt.auth.MqttSignature;
import com.bsj.travel.device.service.DeviceService;
import com.bsj.travel.exception.ApiException;
import com.bsj.travel.security.annotation.RequiresPermissions;
import com.bsj.travel.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author yinhao
 * @version 1.0
 * @description 设备管理类
 * @date 2023/11/14
 */
@Slf4j
@RestController
@RequestMapping(value = "/device")
public class DeviceController {

    @Autowired
    private BaseMqPushUtil baseMqPushUtil;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private DeviceService deviceService;

    /**
     * 发布消息
     *
     * @param topic
     * @return
     */
    @PostMapping(value = "/senMsg")
    public JsonResult senMsg(String topic, String data, String username) {
        MqttEventPublish mqttEventPublish = new MqttEventPublish();
        mqttEventPublish.setTopic(topic);
        mqttEventPublish.setData(JSON.parseObject(data));
        mqttEventPublish.setClient(username);
        mqttEventPublish.setQos(0);
        baseMqPushUtil.sendMqttMsgDownTag(mqttEventPublish);
        return JsonResult.success(mqttEventPublish);
    }

    @GetMapping(value = "/getMqttService")
    public JsonResult getMqttService(String name) {
        List<ServiceInstance> instances = discoveryClient.getInstances(name);
        for (ServiceInstance instance : instances) {
            log.info("服务: {}", instance.getHost());
            String url = instance.getUri() + "/hello";
            RestTemplate restTemplate = new RestTemplate();
            JsonResult forObject = restTemplate.getForObject(url, JsonResult.class);
            log.info(JSON.toJSONString(forObject));
        }
        return JsonResult.success(instances);
    }

    /**
     * 添加设备
     *
     * @param deviceDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/15 10:53
     */
    @PostMapping("/add")
    @RequiresPermissions(value = "device:operation:add")
    public JsonResult add(@Validated DeviceDTO deviceDTO) {
        return deviceService.addDevice(deviceDTO);
    }

    /**
     * 删除设备
     *
     * @param deviceParamDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/15 11:06
     */
    @PostMapping("/delete")
    @RequiresPermissions(value = "device:operation:delete")
    public JsonResult delete(@Validated DeviceParamDTO deviceParamDTO) {
        return deviceService.deleteDevice(deviceParamDTO);
    }

    /**
     * 修改设备
     *
     * @param deviceDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/15 10:55
     */
    @PostMapping("/update")
    @RequiresPermissions(value = "device:operation:update")
    public JsonResult update(@Validated DeviceDTO deviceDTO) {
        return deviceService.updateDevice(deviceDTO);
    }


    /**
     * 修改设备备注
     * @param deviceRemarkDTO
     * @return
     */
    @PostMapping("/updateRemark")
    public JsonResult updateRemark(@Validated DeviceRemarkDTO deviceRemarkDTO) {
        return deviceService.updateRemark(deviceRemarkDTO);
    }

    /**
     * 根据设备id获取设备信息
     *
     * @param deviceParamDTO
     * @return com.bsj.travel.def.global.JsonResult<com.bsj.travel.def.common.VO.device.DeviceCorrelationInfoVO>
     * @author ljx
     * @time 2024/1/15 11:00
     */
    @GetMapping("/getById")
    @RequiresPermissions(value = "device:info:getById")
    public JsonResult<DeviceCorrelationInfoVO> getById(@Validated DeviceParamDTO deviceParamDTO) {
        DeviceCorrelationInfoVO deviceCorrelationInfoVO = deviceService.getDeviceInfoById(deviceParamDTO);
        return JsonResult.success(deviceCorrelationInfoVO);
    }

    /**
     * 数量统计
     *
     * @param
     * @return com.bsj.travel.def.global.JsonResult<java.util.Map < java.lang.String, java.lang.Object>>
     * @author ljx
     * @time 2024/2/18 15:02
     */
    @GetMapping("/quantityCount")
    @RequiresPermissions(value = "device:info:quantityCount")
    public JsonResult<Map<String, Object>> quantityCount() {
        return JsonResult.success(deviceService.quantityCount());
    }

    /**
     * 设备分页
     *
     * @param deviceSearchDTO
     * @return com.bsj.travel.def.global.JsonResult<java.util.List < com.bsj.travel.def.common.VO.device.DeviceVO>>
     * @author ljx
     * @time 2024/1/15 11:09
     */
    @GetMapping("/page")
    @RequiresPermissions(value = "device:info:page")
    public JsonResult<List<DeviceVO>> page(@Validated DeviceSearchDTO deviceSearchDTO) {
        return deviceService.pageDevice(deviceSearchDTO);
    }

    /**
     * 是否禁用
     *
     * @param deviceParamDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/15 12:10
     */
    @PostMapping("/whetherToDisable")
    @RequiresPermissions(value = "device:operation:whetherToDisable")
    public JsonResult whetherToDisable(@Validated DeviceParamDTO deviceParamDTO) {
        return deviceService.whetherToDisable(deviceParamDTO);
    }

    /**
     * 下载设备模板
     *
     * @param response
     * @return void
     * @author ljx
     * @time 2024/2/18 12:04
     */
    @GetMapping("/downloadTemplate")
    public void downloadDeviceTemplate(HttpServletResponse response) throws Exception {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        //编码 防止中文乱码
        String fileName = URLEncoder.encode("设备模板", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DeviceTemplateVO.class).sheet("车辆模板").doWrite(new LinkedList<>());
    }

    /**
     * 批量添加设备
     *
     * @param deviceParamDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/15 14:24
     */
    @PostMapping("/batchAdd")
    @RequiresPermissions(value = "device:operation:batchAdd")
    public JsonResult batchAdd(@Validated DeviceParamDTO deviceParamDTO) {
        return deviceService.batchAddDevice(deviceParamDTO);
    }

    /**
     * 导出设备信息
     *
     * @param response
     * @param deviceSearchDTO
     * @return void
     * @author ljx
     * @time 2024/1/17 19:05
     */
    @GetMapping("/exportDeviceInfo")
    @RequiresPermissions(value = "device:info:exportDeviceInfo")
    public void exportDeviceInfo(HttpServletResponse response, DeviceSearchDTO deviceSearchDTO) throws IOException {
        List<DeviceExcelVO> deviceExcelVOS = deviceService.getDeviceReportData(deviceSearchDTO);
        if (CollectionUtils.isEmpty(deviceExcelVOS)) {
            throw new ApiException(JsonResultEnum.NO_EXPORT_DATA);
        }
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        //编码 防止中文乱码
        String fileName = URLEncoder.encode("车辆操作记录信息" + DateUtils.parseDateToStr(new Date()), "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcelFactory.write(response.getOutputStream(), DeviceExcelVO.class).sheet("设备信息")
                .doWrite(deviceExcelVOS);
    }

    /**
     * 模糊搜索设备号
     *
     * @param productKey
     * @param value
     * @return com.bsj.travel.def.global.JsonResult<java.util.List < java.lang.String>>
     * @author ljx
     * @time 2024/3/20 19:12
     */
    @GetMapping("/fuzzySearchDeviceName")
    @RequiresPermissions(value = "device:info:fuzzySearchDeviceName")
    public JsonResult<List<String>> fuzzySearchDeviceName(String productKey, String value) {
        return JsonResult.success(deviceService.fuzzySearchDeviceName(productKey, value));
    }

    /**
     * 获取MQTT连接参数
     *
     * @param productKey
     * @param deviceName
     * @return com.bsj.travel.def.global.JsonResult<com.bsj.travel.def.mqtt.auth.MqttSignature>
     * @author ljx
     * @time 2024/3/22 14:41
     */
    @GetMapping("/getMqttSignature")
    @RequiresPermissions(value = "device:info:getMqttSignature")
    public JsonResult<MqttSignature> getMqttSignature(String productKey, String deviceName) {
        return JsonResult.success(deviceService.getMqttSignature(productKey, deviceName));
    }

    @GetMapping("/exportMqttSignature")
    public void exportMqttSignature(HttpServletResponse response,String productKey) throws IOException {
        List<MqttSignatureExcelVO> mqttSignatureExcelVOS = deviceService.getMqttSignatureReportData(productKey);
        if (CollectionUtils.isEmpty(mqttSignatureExcelVOS)) {
            throw new ApiException(JsonResultEnum.NO_EXPORT_DATA);
        }
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        //编码 防止中文乱码
        String fileName = URLEncoder.encode("MQTT连接参数", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), MqttSignatureExcelVO.class).sheet("MQTT连接参数").doWrite(mqttSignatureExcelVOS);
    }

    /**
     * 对应主题发布消息
     * @param productKey 产品key
     * @param deviceName 设备号
     * @param topic 主题信息
     * @param data 发布内容
     * @return
     */
    @PostMapping(value = "/pubMqttMsg")
    @RequiresPermissions(value = "device:info:pubMqttMsg")
    public JsonResult pubMqttMsg(String productKey, String deviceName,
                                 String topic, String data, Integer qos) {
        if (productKey == null || deviceName == null || topic == null || data == null) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR);
        }
        return deviceService.pubMqttMsg(productKey, deviceName, topic, data, qos);
    }

}
